from langchain_deepseek import ChatDeepSeek
from langchain_core.output_parsers import StrOutputParser
from langchain.prompts import ChatPromptTemplate
import os
from dotenv import load_dotenv
import json
import time
from datetime import datetime
from typing import Dict, Any, List, Optional, Union, Callable
from dataclasses import dataclass

try:
    from .prompts import (
        create_base_chat_prompt,
        create_base_chat_prompt_template,
        create_structured_output_prompt,
        create_structured_output_prompt_template,
        create_classification_prompt,
        create_classification_prompt_template
    )
    from .tools import (
        get_current_time,
        get_current_date, 
        get_weather_info,
        search_knowledge_base,
        get_available_tools_description,
        get_tool_by_name,
        validate_input,
        format_response,
        # 智能客服功能
        analyze_customer_sentiment,
        categorize_customer_query,
        handle_order_inquiry,
        generate_faq_response,
        escalate_to_human_agent,
        provide_contact_info,
        suggest_similar_products,
        track_customer_satisfaction,
        generate_smart_reply_suggestions,
        CustomerServiceSession
    )
    from ..utils.memory import ConversationMemory, ContextManager
    from ..utils.helpers import (
        setup_logging,
        clean_text,
        parse_query_params,
        ResponseFormatter,
        extract_json_from_text
    )
    from ..config.settings import settings, validate_settings
except ImportError:
    # 绝对导入
    from assistant.prompts import (
        create_base_chat_prompt,
        create_base_chat_prompt_template,
        create_structured_output_prompt,
        create_structured_output_prompt_template,
        create_classification_prompt,
        create_classification_prompt_template
    )
    from assistant.tools import (
        get_current_time,
        get_current_date, 
        get_weather_info,
        search_knowledge_base,
        get_available_tools_description,
        get_tool_by_name,
        validate_input,
        format_response,
        # 智能客服功能
        analyze_customer_sentiment,
        categorize_customer_query,
        handle_order_inquiry,
        generate_faq_response,
        escalate_to_human_agent,
        provide_contact_info,
        suggest_similar_products,
        track_customer_satisfaction,
        generate_smart_reply_suggestions,
        CustomerServiceSession
    )
    from utils.memory import ConversationMemory, ContextManager
    from utils.helpers import (
        setup_logging,
        clean_text,
        parse_query_params,
        ResponseFormatter,
        extract_json_from_text
    )
    from config.settings import settings, validate_settings


@dataclass
class ThinkingStep:
    """思考步骤数据类"""
    step_id: int
    step_name: str
    description: str
    start_time: float
    end_time: Optional[float] = None
    result: Optional[str] = None
    details: Optional[Dict[str, Any]] = None
    
    def duration(self) -> float:
        """计算步骤耗时"""
        if self.end_time:
            return self.end_time - self.start_time
        return 0.0

class ThinkingProcess:
    """思考过程追踪器"""
    
    def __init__(self):
        self.steps: List[ThinkingStep] = []
        self.current_step_id = 0
        self.start_time = time.time()
        
    def add_step(self, step_name: str, description: str) -> ThinkingStep:
        """添加思考步骤"""
        self.current_step_id += 1
        step = ThinkingStep(
            step_id=self.current_step_id,
            step_name=step_name,
            description=description,
            start_time=time.time()
        )
        self.steps.append(step)
        return step
    
    def complete_step(self, step: ThinkingStep, result: str, details: Optional[Dict[str, Any]] = None):
        """完成思考步骤"""
        step.end_time = time.time()
        step.result = result
        step.details = details or {}
    
    def get_summary(self) -> Dict[str, Any]:
        """获取思考过程摘要"""
        total_time = time.time() - self.start_time
        return {
            "total_steps": len(self.steps),
            "total_time": round(total_time, 3),
            "steps": [
                {
                    "id": step.step_id,
                    "name": step.step_name,
                    "description": step.description,
                    "duration": round(step.duration(), 3),
                    "result": step.result,
                    "details": step.details
                }
                for step in self.steps
            ]
        }
    
    def format_for_display(self) -> str:
        """格式化用于显示的思考过程"""
        lines = ["🧠 **AI思考过程**", ""]
        
        for step in self.steps:
            lines.append(f"**{step.step_id}. {step.step_name}**")
            lines.append(f"   📝 {step.description}")
            if step.result:
                lines.append(f"   ✅ 结果: {step.result}")
            lines.append(f"   ⏱️ 耗时: {step.duration():.3f}秒")
            lines.append("")
        
        total_time = time.time() - self.start_time
        lines.append(f"🎯 **总耗时**: {total_time:.3f}秒")
        lines.append("---")
        
        return "\n".join(lines)

class SmartAssistant:
    """智能客服助手核心类"""
    
    def __init__(self, model: Optional[str] = None, temperature: Optional[float] = None):
        """
        初始化智能助手
        
        Args:
            model: 模型名称，默认使用配置中的模型
            temperature: 温度参数，默认使用配置中的参数
        """
        # 加载环境变量（在 Streamlit 环境中跳过重新加载）
        import os
        from pathlib import Path
        
        # 检查是否在 Streamlit 环境中运行
        in_streamlit = 'streamlit' in os.environ.get('_', '') or hasattr(__builtins__, '__IPYTHON__') or 'streamlit' in str(type(__builtins__))
        
        if not in_streamlit:
            # 确保从项目根目录加载 .env 文件
            project_root = Path(__file__).parent.parent
            env_path = project_root / ".env"
            load_dotenv(env_path)
        
        # 验证配置（使用当前环境变量）
        api_key = os.environ.get("SILICONFLOW_API_KEY", "")
        api_base = os.environ.get("SILICONFLOW_API_BASE", "")
        
        if not api_key:
            raise RuntimeError("SILICONFLOW_API_KEY 未设置，请在 .env 文件中配置")
        if not api_base:
            raise RuntimeError("SILICONFLOW_API_BASE 未设置，请在 .env 文件中配置")
        
        # 设置日志
        self.logger = setup_logging()
        
        # 初始化模型
        self.model_name = model or os.environ.get("DEFAULT_MODEL", "deepseek-ai/DeepSeek-R1-0528-Qwen3-8B")
        self.temperature = temperature if temperature is not None else float(os.environ.get("DEFAULT_TEMPERATURE", "0.7"))
        
        try:
            self.llm = ChatDeepSeek(
                model=self.model_name,
                temperature=self.temperature,
                api_key=api_key,
                base_url=api_base,
                timeout=int(os.environ.get("DEFAULT_TIMEOUT", "60"))
            )
            
            # 手动修复 ChatDeepSeek 的 base_url 问题
            # ChatDeepSeek 可能没有正确使用 base_url 参数，需要手动设置
            try:
                if hasattr(self.llm, 'client') and hasattr(self.llm.client, '_client'):
                    # 修复底层 OpenAI 客户端的 base_url
                    self.llm.client._client.base_url = settings.siliconflow_api_base
                elif hasattr(self.llm, '_client'):
                    # 直接修复 OpenAI 客户端的 base_url
                    self.llm._client.base_url = settings.siliconflow_api_base
            except Exception as fix_error:
                self.logger.warning(f"无法修复 base_url，将使用默认设置: {fix_error}")
            
            self.logger.info(f"成功初始化模型: {self.model_name}")
        except Exception as e:
            self.logger.error(f"模型初始化失败: {e}")
            raise RuntimeError(f"无法初始化AI模型: {e}")
        
        # 初始化组件
        self.memory = ConversationMemory(max_messages=settings.conversation_history_limit)
        self.context_manager = ContextManager()
        self.output_parser = StrOutputParser()
        
        # 初始化思考过程追踪
        self.show_thinking = True  # 默认显示思考过程
        self.current_thinking: Optional[ThinkingProcess] = None
        
        # 创建提示词模板
        self.chat_prompt = create_base_chat_prompt_template()
        self.structured_prompt = create_structured_output_prompt_template()
        self.classification_prompt = create_classification_prompt_template()
        
        # 创建处理链
        self.chat_chain = self.chat_prompt | self.llm | self.output_parser
        self.structured_chain = self.structured_prompt | self.llm | self.output_parser
        self.classification_chain = self.classification_prompt | self.llm | self.output_parser
        
        self.logger.info("智能助手初始化完成")
    
    def chat(self, user_input: str, use_tools: bool = True, show_thinking: Optional[bool] = None, stream: bool = False) -> Union[str, Any]:
        """
        基础对话功能
        
        Args:
            user_input: 用户输入
            use_tools: 是否使用工具
            show_thinking: 是否显示思考过程，None时使用默认设置
            stream: 是否使用流式输出
            
        Returns:
            助手回复或流式生成器
        """
        # 使用默认思考设置
        if show_thinking is None:
            show_thinking = self.show_thinking
            
        try:
            # 快速验证输入
            if not validate_input(user_input):
                return "抱歉，请提供有效的输入内容。"
            
            user_input = clean_text(user_input)
            
            # 记录用户消息
            self.memory.add_message("user", user_input)
            
            # 快速解析参数
            query_params = parse_query_params(user_input)
            
            # 工具调用（如果需要）
            tool_result = None
            if use_tools:
                tool_result = self._try_use_tools(user_input, query_params)
            
            # 构建输入数据
            chat_history = self.memory.get_formatted_history(last_n=3)  # 进一步减少历史记录
            input_data = {
                "user_input": user_input if not tool_result else f"{user_input}\n\n工具查询结果：{tool_result}",
                "chat_history": chat_history
            }
            
            # 根据输出模式选择处理方式
            if stream:
                # 流式输出模式
                if show_thinking:
                    thinking_prompt = ChatPromptTemplate.from_messages([
                        ("system", """你是一个智能客服助手。请严格按以下格式回复：

🧠 **思考过程**：
[简要描述你的分析思路，1-2句话]

💬 **回复**：
[给出详细的解答或建议]

要求：思考过程要简洁直接，展示核心推理。

对话历史：{chat_history}"""),
                        ("user", "{user_input}")
                    ])
                    chain = thinking_prompt | self.llm | self.output_parser
                else:
                    chain = self.chat_chain
                
                return self._stream_response(chain, input_data)
            else:
                # 传统模式：一次性输出
                if show_thinking:
                    thinking_prompt = ChatPromptTemplate.from_messages([
                        ("system", """你是一个智能客服助手。请按以下格式回复：

🧠 **思考过程**：
[简要描述你的思考过程，1-2句话即可]

💬 **回复**：
[给出具体回复]

要求：思考过程要简洁，直接展示推理思路。

对话历史：{chat_history}"""),
                        ("user", "{user_input}")
                    ])
                    chain = thinking_prompt | self.llm | self.output_parser
                else:
                    chain = self.chat_chain
                
                response = chain.invoke(input_data)
                self.memory.add_message("assistant", response)
                return response
            
        except Exception as e:
            error_msg = f"对话处理出错: {str(e)}"
            self.logger.error(error_msg)
            return "抱歉，处理您的请求时出现了错误，请稍后再试。"
    
    def _stream_response(self, chain, input_data):
        """
        流式响应生成器
        
        Args:
            chain: 处理链
            input_data: 输入数据
            
        Yields:
            逐步生成的响应内容片段（增量内容）
        """
        try:
            response_content = ""
            
            # 使用stream方法获取流式输出
            for chunk in chain.stream(input_data):
                if chunk:
                    response_content += chunk
                    # 只yield增量内容（chunk），前端负责累积
                    yield chunk
            
            # 流式输出完成后记录完整回复
            if response_content:
                self.memory.add_message("assistant", response_content)
                
        except Exception as e:
            error_msg = f"流式输出错误: {str(e)}"
            self.logger.error(error_msg)
            yield f"❌ 错误: {error_msg}"
    
    def structured_query(self, user_input: str, output_format: str = "json") -> Dict[str, Any]:
        """
        结构化查询功能
        
        Args:
            user_input: 用户输入
            output_format: 输出格式 (json/xml/table)
            
        Returns:
            结构化结果
        """
        try:
            if not validate_input(user_input):
                return ResponseFormatter.format_error("无效的输入内容")
            
            # 调用结构化输出链
            input_data = {
                "user_input": clean_text(user_input),
                "output_format": output_format
            }
            
            response = self.structured_chain.invoke(input_data)
            
            # 尝试解析JSON响应
            if output_format.lower() == "json":
                json_data = extract_json_from_text(response)
                if json_data:
                    return ResponseFormatter.format_success(json_data)
            
            return ResponseFormatter.format_success({
                "content": response,
                "format": output_format
            })
            
        except Exception as e:
            error_msg = f"结构化查询出错: {str(e)}"
            self.logger.error(error_msg)
            return ResponseFormatter.format_error(error_msg)
    
    def classify_intent(self, user_input: str) -> str:
        """
        意图分类
        
        Args:
            user_input: 用户输入
            
        Returns:
            分类结果
        """
        try:
            if not validate_input(user_input):
                return "other"
            
            response = self.classification_chain.invoke({
                "user_input": clean_text(user_input)
            })
            
            # 清理分类结果
            classification = clean_text(response.strip().lower())
            
            # 验证分类结果
            valid_categories = [
                "general_inquiry", "technical_support", "complaint",
                "information_request", "weather_query", "time_query", "other"
            ]
            
            if classification in valid_categories:
                return classification
            else:
                return "other"
                
        except Exception as e:
            self.logger.error(f"意图分类出错: {str(e)}")
            return "other"
    
    def get_conversation_summary(self) -> Dict[str, Any]:
        """获取对话摘要"""
        return self.memory.get_conversation_summary()
    
    def clear_conversation(self):
        """清空对话历史"""
        self.memory.clear_history()
        self.context_manager.clear_context()
        self.logger.info("对话历史已清空")
    
    def set_user_preference(self, key: str, value: Any):
        """设置用户偏好"""
        self.context_manager.set_user_preference(key, value)
    
    def get_user_preference(self, key: str, default: Any = None) -> Any:
        """获取用户偏好"""
        return self.context_manager.get_user_preference(key, default)
    
    def set_thinking_mode(self, show_thinking: bool):
        """
        设置是否显示思考过程
        
        Args:
            show_thinking: True显示思考过程，False隐藏
        """
        self.show_thinking = show_thinking
        self.logger.info(f"思考过程显示模式设置为: {'开启' if show_thinking else '关闭'}")
    
    def get_thinking_summary(self) -> Optional[Dict[str, Any]]:
        """
        获取最后一次思考过程的摘要
        
        Returns:
            思考过程摘要或None
        """
        if self.current_thinking:
            return self.current_thinking.get_summary()
        return None

    def _try_use_tools(self, user_input: str, query_params: Dict[str, Any]) -> Optional[str]:
        """
        尝试使用工具处理用户请求
        
        Args:
            user_input: 用户输入
            query_params: 查询参数
            
        Returns:
            工具处理结果
        """
        try:
            query_type = query_params.get('query_type', 'general')
            
            # 时间查询
            if query_type == 'time' or any(keyword in user_input for keyword in ['时间', '几点', '现在']):
                return get_current_time()
            
            # 天气查询
            elif query_type == 'weather' or any(keyword in user_input for keyword in ['天气', '气温', '温度']):
                city = query_params.get('city', '北京')
                # 尝试从用户输入中提取城市名
                for city_name in ['北京', '上海', '广州', '深圳', '杭州', '南京', '武汉', '成都']:
                    if city_name in user_input:
                        city = city_name
                        break
                weather_info = get_weather_info(city)
                return f"{city}天气：{weather_info['weather']}，温度{weather_info['temperature']}，{weather_info['forecast']}"
            
            # 知识库查询 - 扩展触发条件
            elif (query_type in ['return_policy', 'shipping', 'knowledge'] or 
                  any(keyword in user_input for keyword in [
                      '退货', '退款', '换货', '政策', '规定', '配送', '物流', '发货', 
                      '客服', '联系', '电话', '支付', '付款', '会员', '积分', '发票',
                      '保修', '维修', '售后', '服务', '时间', '工作', '营业'
                  ])):
                
                # 尝试知识库搜索
                knowledge_result = search_knowledge_base(user_input)
                if knowledge_result:
                    return f"📚 根据我们的政策和服务信息：{knowledge_result}"
                
                # 如果知识库没有找到，尝试基于关键词提供基础信息
                if '退货' in user_input or '退款' in user_input:
                    return "📚 根据我们的政策和服务信息：我们支持7天无理由退货，商品需保持原包装完好。具体退货流程请联系客服。"
                elif '配送' in user_input or '物流' in user_input or '发货' in user_input:
                    return "📚 根据我们的政策和服务信息：一般情况下，订单会在24小时内发货，3-5个工作日内送达。"
                elif '客服' in user_input or '联系' in user_input:
                    return "📚 根据我们的政策和服务信息：我们的客服工作时间是周一至周日 9:00-18:00，客服电话：400-123-4567。"
                elif '支付' in user_input or '付款' in user_input:
                    return "📚 根据我们的政策和服务信息：我们支持微信支付、支付宝、银行卡等多种支付方式。"
                elif '会员' in user_input:
                    return "📚 根据我们的政策和服务信息：会员享有专属折扣、优先客服、生日礼品等多项权益。"
                elif '发票' in user_input:
                    return "📚 根据我们的政策和服务信息：我们支持开具电子发票和纸质发票，请在下单时选择发票类型。"
                elif '积分' in user_input:
                    return "📚 根据我们的政策和服务信息：消费1元获得1积分，积分可用于兑换优惠券和礼品。"
                elif '售后' in user_input or '保修' in user_input or '维修' in user_input:
                    return "📚 根据我们的政策和服务信息：产品出现质量问题，我们提供免费维修或更换服务。"
            
            # 订单查询
            elif '订单' in user_input:
                import re
                order_pattern = r'\b\d{10,15}\b'
                order_matches = re.findall(order_pattern, user_input)
                if order_matches:
                    order_id = order_matches[0]
                    order_result = handle_order_inquiry(order_id)
                    if order_result.get("success"):
                        order_info = order_result["order_info"]
                        return f"📦 订单查询结果：\n订单号：{order_id}\n状态：{order_info['status']}\n预计送达：{order_info['estimated_delivery']}"
                    else:
                        return f"❌ {order_result.get('message', '订单查询失败')}"
                else:
                    return "📦 请提供您的订单号，我来帮您查询订单状态。订单号通常是10-15位数字。"
            
            return None
            
        except Exception as e:
            self.logger.error(f"工具调用出错: {str(e)}")
            return None
    
    def get_available_functions(self) -> List[str]:
        """获取可用功能列表"""
        return [
            "基础对话",
            "结构化查询", 
            "意图分类",
            "获取时间",
            "查询天气",
            "知识库搜索",
            "对话历史管理"
        ]
    
    def health_check(self) -> Dict[str, Any]:
        """健康检查"""
        try:
            # 测试模型连接
            test_response = self.llm.invoke([{"role": "user", "content": "你好"}])
            
            return {
                "status": "healthy",
                "model": self.model_name,
                "temperature": self.temperature,
                "conversation_count": len(self.memory.conversation_history),
                "test_response_length": len(str(test_response)),
                "timestamp": self._get_current_timestamp()
            }
        except Exception as e:
            return {
                "status": "unhealthy",
                "error": str(e),
                "timestamp": self._get_current_timestamp()
            }
    
    def _get_current_timestamp(self) -> str:
        """获取当前时间戳"""
        import datetime
        return datetime.datetime.now().isoformat()
